/*******************************************************************************
 * 文件名: XMLParser.java
 * 描    述: XML解析
 * 创建人: Dean Huang(hudi-112@163.com)
 * 日　期: 2017-12-22
 * 描　述: 文件描述
 * 版　本: 1.0
 *******************************************************************************/

package com.z1.core.xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import com.z1.core.exception.Z1Exception;

public class XMLParser {
	
    private Document document = null;

    private XMLParser(File file) {
    	try {
    		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    		DocumentBuilder builder = factory.newDocumentBuilder();
    		document = builder.parse(new FileInputStream(file));
    	}
    	catch (Throwable e) {
    		throw new Z1Exception(e);
    	}
    }
    private XMLParser(InputStream input) {
    	try {
	    	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	    	DocumentBuilder builder = factory.newDocumentBuilder();
	    	document = builder.parse(input);
    	}
    	catch (Throwable e) {
    		throw new Z1Exception(e);
    	}
    }
    
    public Document getDocument() {
    	return document;
    }

    public final Node getRootNode() {
        if (null == document) {
            return null;
        }
        for (Node node = document.getFirstChild();  
        	node != null; 
        	node = node.getNextSibling()) {
        	if(node.getNodeType() == Node.ELEMENT_NODE) {
                return node;
            }
        }
        return null;
    }

    public static final Node getElementByTag(Node element, String tag) {
        if(element.getNodeType() != Node.ELEMENT_NODE) {
            return null;
        }
        if(element.getNodeName().equalsIgnoreCase(tag)) {
            return element;
        }
        for (Node node = element.getFirstChild();
        	node != null;
        	node = node.getNextSibling()) {
            Node e = getElementByTag(node, tag);
            if (null != e) {
                return e;
            }
        }
        return null;
    }

    public static final Node getFirstChildElement( Node element )
    {
        for (Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                return node;
            }
        }
        return null;
    }
    
    public static final Node getLastChildElement(Node element) {
        Node e = null;
        for (Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                e = node;
            }
        }
        return e;
    }

    public static final int countChildElement(Node element) {
        int i = 0;
        for (Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                i += 1;
            }
        }

        return i;
    }
    
    public static final Node getChildElementByTag(Node element, String tag) {
        for (Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(tag)) {
            	return node;
            }
        }
        return null;
    }
    
    public static final List<Node> getChildElementsByTag(Node element, String tag) {
    	List<Node> nodes = new ArrayList<Node>();
        for (Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(tag)) {
            	nodes.add(node);
            }
        }
        return nodes;
    }

    public static final String getElementValue(Node element) {
        for(Node node = element.getFirstChild(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == Node.TEXT_NODE) {
                return node.getNodeValue();
            }
        }
        return "";
    }

    public static final String getElementAttr(Node element, String attrName) {
        NamedNodeMap map = element.getAttributes();
        int i = 0;
        for (Node n = map.item(i); n != null; n = map.item(i)) {
            if (n.getNodeType() == Node.ATTRIBUTE_NODE &&
                n.getNodeName().equalsIgnoreCase(attrName)) {
                return n.getNodeValue();
            }
            i++;
        }
        return "";
    }

    public static final Item[] getElementAttrs(Node element) {
        List<Item> list = new ArrayList<Item>();
        NamedNodeMap map = element.getAttributes();
        int i = 0;
        for( Node n = map.item(i); n != null; n = map.item(i)) {
            if(n.getNodeType() == Node.ATTRIBUTE_NODE) {
                Item item = new Item(n.getNodeName(), n.getNodeValue());
                list.add(item);
            }
            i++;
        }
        Item items[] = new Item[list.size()];
        list.toArray(items);
        return items;
    }

    public static final Node getNextSibling(Node element) {
        for(Node node = element.getNextSibling(); 
        	node != null; 
        	node = node.getNextSibling()) {
            if (node.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
            	return node;
            }
        }
        return null;
    }

    public static final Element nextSibling(Node e) {
        for(Node node = e.getNextSibling(); 
        	node != null;
        	node = node.getNextSibling()) {
            if (node.getNodeType() != Node.ELEMENT_NODE) {
                continue;
            }
            if (e.getNodeName().equalsIgnoreCase(node.getNodeName())) {
                return (Element)node;
            }
        }
        return null;
    }

    public static final XMLParser createXMLParser(String path) {
    	return createXMLParser(new File(path));
    }
    
    public static final XMLParser createXMLParser(File file) {
    	if (file.exists()) {
    		return new XMLParser(file);
        }
        else {
            throw new Z1Exception("Unknown xml file:" + file.getPath());
        }
    }
    
    public static final XMLParser createXMLParser(InputStream input) {
    	if (null != input) {
    		return new XMLParser(input);
        }
        else {
            throw new Z1Exception("InputStream  is  null");
        }
    }
    
    public String toString() {
        return getRootNode().toString();
    }

}
